using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;

namespace XnaDevRu.BulletX
{
	/// <summary>
	/// PHY_ScalarType enumerates possible scalar types.
	/// See the StridingMeshInterface for its use
	/// </summary>
	public enum PHY_ScalarType
	{
		PHY_FLOAT,
		PHY_DOUBLE,
		PHY_INTEGER,
		PHY_SHORT,
		PHY_FIXEDPOINT88
	}

	/// <summary>
	/// StridingMeshInterface is the interface class for high performance access to triangle meshes
	/// It allows for sharing graphics and collision meshes. Also it provides locking/unlocking of graphics meshes that are in gpu memory.
	/// </summary>
	public abstract class StridingMeshInterface
	{
		protected Vector3 _scaling;

		public StridingMeshInterface()
		{
			_scaling = new Vector3(1f,1f,1f);
		}

		public void InternalProcessAllTriangles(ITriangleIndexCallback callback, Vector3 aabbMin, Vector3 aabbMax)
		{
			int numtotalphysicsverts = 0;
            int numtriangles, gfxindex;
			int part, graphicssubparts = SubPartsCount();
            Vector3[] triangle = new Vector3[3];
            List<Vector3> verts;
            List<int> indicies;

			Vector3 meshScaling = Scaling;

			//if the number of parts is big, the performance might drop due to the innerloop switch on indextype
			for (part = 0; part < graphicssubparts; part++)
			{
                GetLockedReadOnlyVertexIndexBase(out verts, out indicies, out numtriangles, part);
			    numtotalphysicsverts += numtriangles * 3; //upper bound

                for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
                {
                    triangle[0] = verts[indicies[gfxindex * 3 + 0]];
                    triangle[1] = verts[indicies[gfxindex * 3 + 1]];
                    triangle[2] = verts[indicies[gfxindex * 3 + 2]];

                    callback.ProcessTriangleIndex(triangle, part, gfxindex);
                }

			    UnLockReadOnlyVertexBase(part);
			}
		}


		/// get read and write access to a subpart of a triangle mesh
		/// this subpart has a continuous array of vertices and indices
		/// in this way the mesh can be handled as chunks of memory with striding
		/// very similar to OpenGL vertexarray support
		/// make a call to unLockVertexBase when the read and write access is finished	
		public abstract void GetLockedVertexIndexBase(out List<Vector3> verts, out List<int> indicies, out int numfaces, int subpart);

        public abstract void GetLockedReadOnlyVertexIndexBase(out List<Vector3> verts, out List<int> indicies, out int numfaces, int subpart);
	
		/// unLockVertexBase finishes the access to a subpart of the triangle mesh
		/// make a call to unLockVertexBase when the read and write access (using getLockedVertexIndexBase) is finished
		public abstract void UnLockVertexBase(int subpart);

		public abstract void UnLockReadOnlyVertexBase(int subpart);


		/// getNumSubParts returns the number of seperate subparts
		/// each subpart has a continuous array of vertices and indices
        public abstract int SubPartsCount();

		public abstract void PreallocateVertices(int numverts);
		public abstract void PreallocateIndices(int numindices);

		public Vector3 Scaling
        {           
			get { return _scaling; }
            set { _scaling = value; }
		}
	}
}
